/**
 * 
 */
package com.haoho.commons.dao.impl;

import java.io.File;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;

import com.haoho.commons.dao.GenericDao;

/**
 * @param T
 *            domain object
 * @param PK
 *            primary key
 * @author hthao
 * 
 */
public class GenericDaoImpl<T, PK extends Serializable> implements
		GenericDao<T, PK> {

	private Class<T> persistentClass;

	/**
	 * SessionFactory for this DAO.
	 */
	private SessionFactory sessionFactory;

	/**
	 * @return the persistentClass
	 */
	protected Class<T> getPersistentClass() {
		return persistentClass;
	}

	/**
	 * @return the sessionFactory
	 */
	protected SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	/**
	 * @param sessionFactory
	 *            the sessionFactory to set
	 */
	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	@SuppressWarnings("unchecked")
	public GenericDaoImpl() {
		this.persistentClass = (Class<T>) ((ParameterizedType) getClass()
				.getGenericSuperclass()).getActualTypeArguments()[0];
	}

	/**
	 * Evicts one entity.
	 * 
	 * @param entity
	 *            entity
	 * @return evicted entity
	 */
	protected T evict(T entity) {
		Session session = getSessionFactory().getCurrentSession();
		session.evict(entity);
		return entity;
	}

	/**
	 * Evicts multiple entities.
	 * 
	 * @param entities
	 *            multiple entities
	 * @return evicted entities
	 */
	protected List<T> evict(List<T> entities) {
		Session session = getSessionFactory().getCurrentSession();
		for (Object object : entities) {
			session.evict(object);
		}
		return entities;
	}

	@SuppressWarnings("unchecked")
	public T findById(PK id) {
		Session session = getSessionFactory().getCurrentSession();
		T result = (T) session.get(getPersistentClass(), id);
		return evict(result);
	}

	/**
	 * Update state of a detached entity to database. But keep this object
	 * detached.
	 * 
	 * @param entity detached entity
	 */
	public void update(T entity) {
		Session session = getSessionFactory().getCurrentSession();
		session.merge(entity);
	}

	/**
	 * Inserts this NEW entity into database.
	 * 
	 * @param entity entity
	 */
	public void create(T entity) {
		Session session = getSessionFactory().getCurrentSession();
		session.save(entity);
	}

	/**
	 * Deletes entity.
	 * 
	 * @param id entity ID
	 */
	public void delete(PK id) {
		Session session = getSessionFactory().getCurrentSession();
		session.delete(session.get(getPersistentClass(), id));
	}

	/**
	 * @see GenericDao
	 */
	public void runSqlScriptFiles(String path) throws Exception {
		if (!path.endsWith(String.valueOf(File.separatorChar))) {
			Session session = getSessionFactory().getCurrentSession();
			Query sql = session.createSQLQuery("");

		}
	}
}
